package cn.ahaoweb.drule.core.model.enums;

import cn.ahaoweb.drule.core.model.annotations.ClassAnn;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * @Name: 对象树中的节点类型
 * @Description:
 * @Author: wangzhonghao
 * @Date: 2025/1/26 13:56
 */
public enum NodeType {

    /**
     * 规则对象类型（被{@link ClassAnn}注解的对象）
     */
    RULE_OBJECT,

    /**
     * 字符串类型
     */
    STRING,

    /**
     * 布尔类型
     */
    BOOL,

    /**
     * 字符类型
     */
    CHAR,

    /**
     * 数值类型，如 {@link java.math.BigDecimal}。
     */
    NUMBER,

    /**
     * 规则对象列表
     */
    LIST_OF_RULE_OBJECT,

    /**
     * 字符串列表
     */
    LIST_OF_STRING,

    /**
     * 字符列表
     */
    LIST_OF_CHAR,

    /**
     * 数值列表
     */
    LIST_OF_NUMBER,

    /**
     * 其它对象列表
     */
    LIST_OF_OTHER,

    /**
     * MAP类型，k和v都为字符串类型
     */
    MAP_STRING_STRING,

    /**
     * MAP类型，k为字符串类型，v为数值类型
     */
    MAP_STRING_NUMBER,

    /**
     * MAP类型，k为字符串类型，v为OBJECT类型
     */
    MAP_STRING_OBJECT,

    /**
     * MAP类型，k为数值类型，v为字符串类型
     */
    MAP_NUMBER_STRING,

    /**
     * MAP类型，除上述map类型之外
     */
    MAP,

    /**
     * 其他类型
     */
    OTHER;

    public static NodeType type(Field field) {
        return type(field.getType(),field.getGenericType());
    }

    /**
     * 获取节点类型
     *
     * @return
     */
    public static NodeType type(Class<?> type, Type genericType) {
        // 优先处理泛型信息
        ParameterizedTypeImpl ge = null;
        if (genericType != null && genericType instanceof ParameterizedTypeImpl){
            ge = (ParameterizedTypeImpl) genericType;
        }
        // 判断规则对象类型
        ClassAnn classInfoAnn = type.getAnnotation(ClassAnn.class);
        if (classInfoAnn != null) {
            return RULE_OBJECT;
        }
        // 判断字段类型
        if (String.class.equals(type)) {
            return STRING;
        }
        if (Boolean.class.equals(type)) {
            return BOOL;
        }
        if (Character.class.equals(type)) {
            return CHAR;
        }
        if (Number.class.isAssignableFrom(type)) {
            return NUMBER;
        }
        // 判断列表类型
        if (ge != null) {
            if (List.class.isAssignableFrom(type)) {
                // 获取带泛型参数的类型
                Type[] actualTypeArguments = ge.getActualTypeArguments();
                Class parameterizedType = (Class) actualTypeArguments[0];
                if (String.class.equals(parameterizedType)) {
                    return LIST_OF_STRING;
                } else if (Character.class.equals(parameterizedType)) {
                    return LIST_OF_CHAR;
                } else if (Number.class.isAssignableFrom(parameterizedType)) {
                    return LIST_OF_NUMBER;
                } else {
                    Annotation annotation = parameterizedType.getAnnotation(ClassAnn.class);
                    if (annotation != null) {
                        return LIST_OF_RULE_OBJECT;
                    } else {
                        return LIST_OF_OTHER;
                    }
                }
            }
            if (Map.class.isAssignableFrom(type)) {
                // 获取带泛型参数的类型
                Type[] actualTypeArguments = ge.getActualTypeArguments();
                Class k = (Class) actualTypeArguments[0];
                Class v = (Class) actualTypeArguments[1];
                if (String.class.equals(k)) {
                    if (String.class.equals(v)) {
                        return MAP_STRING_STRING;
                    } else if (Number.class.isAssignableFrom(v)) {
                        return MAP_STRING_NUMBER;
                    } else {
                        return MAP_STRING_OBJECT;
                    }
                } else if (Number.class.isAssignableFrom(k) && String.class.equals(v)) {
                    return MAP_NUMBER_STRING;
                }
                return MAP;
            }
        }
        return OTHER;
    }

    /**
     * 判断给定的节点类型是否为列表类型
     *
     * @param nodeType 节点类型
     * @return 如果节点类型为列表类型，则返回true；否则返回false
     */
    public static boolean isList(NodeType nodeType){
        return nodeType != null && nodeType.toString().startsWith("LIST");
    }

}
